package com.fire.control.system.module.system.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.fire.control.system.config.redis.RedisService;
import com.fire.control.system.dto.SysLogResultDTO;
import com.fire.control.system.dto.UserDTO;
import com.fire.control.system.entity.Company;
import com.fire.control.system.entity.Resource;
import com.fire.control.system.entity.Role;
import com.fire.control.system.entity.SystemLog;
import com.fire.control.system.entity.User;
import com.fire.control.system.module.company.dao.ManagementRepository;
import com.fire.control.system.module.device.dao.ChargePersonRepository;
import com.fire.control.system.module.system.dao.ResourceRepository;
import com.fire.control.system.module.system.dao.RoleRepository;
import com.fire.control.system.module.system.dao.SystemLogRepository;
import com.fire.control.system.module.system.service.IAccountManagerService;
import com.fire.control.system.module.user.dao.UserMapper;
import com.fire.control.system.module.user.dao.UserRepository;
import com.fire.control.system.statics.Message_Response;
import com.fire.control.system.statics.ResponseMessage;
import com.fire.control.system.support.protocol.account.AccountRequestProtocol;
import com.fire.control.system.support.protocol.comman.ProtocolSelector;
import com.fire.control.system.support.protocol.comman.ResponseProtocol;
import com.fire.control.system.support.protocol.login.LoginRequestProtocol;
import com.fire.control.system.support.util.ResultPageUtil;
import com.fire.control.system.support.util.SmsUtil;
import com.fire.control.system.support.util.XdaoDate;
import com.fire.control.system.support.util.XdaoPassword;
import com.github.pagehelper.PageInfo;

/**
 * @author liuxincheng
 * @ClassName: RoleManagerServiceImpl
 * @Description: TODO(账号管理服务实现)
 * @date 2017年5月20日 下午5:06:50
 */
@Service
public class AccountManagerServiceImpl implements IAccountManagerService {

	@Autowired
	private ProtocolSelector protocolSelector;

	@Autowired
	private RoleRepository roleRepository;

	@Autowired
	private ResourceRepository resourceRepository;

	@Autowired
	private ChargePersonRepository accountRepositoty;

	@Autowired
	private ManagementRepository companyRepository;

	@Autowired
	private SystemLogRepository systemLogRepository;

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private RedisService redisService;

	@Autowired
	private ResultPageUtil resultPageUtil;

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private SmsUtil smsUtil;

	/**
	 * <p>
	 * Title: getCountList
	 * </p>
	 * <p>
	 * Description:获得账号列表
	 * </p>
	 * 
	 * @param protocol
	 * @param p
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#getCountList(com.fire.control.system.support.protocol.account.AccountRequestProtocol,
	 *      org.springframework.data.domain.Pageable)
	 */
	@Override
	public ResponseProtocol getCountList(AccountRequestProtocol protocol, Pageable p) {
		// TODO Auto-generated method stub
		ResponseProtocol response = protocolSelector.choose(protocol);

		Page<User> accountList = accountRepositoty.findAll(p);

		if (!accountList.equals(null)) {
			response.setData(accountList);
			response.setIsSuccess(true);
			response.setDate(new XdaoDate());
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("数据返回成功!");
		} else {
			response.setData(null);
			response.setIsSuccess(false);
			response.setDate(new XdaoDate());
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("数据返回失败!");
		}
		return response;
	}

	/**
	 * <p>
	 * Title: getCountListByCondition
	 * </p>
	 * <p>
	 * Description: 通过条件获得账号列表
	 * </p>
	 * 
	 * @param protocol
	 * @param p
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#getCountListByCondition(com.fire.control.system.support.protocol.account.AccountRequestProtocol,
	 *      org.springframework.data.domain.Pageable)
	 */
	@Override
	public ResponseProtocol getCountListByCondition(AccountRequestProtocol protocol, Pageable p) {
		ResponseProtocol response = protocolSelector.choose(protocol);

		Page<User> companyPage = accountRepositoty.findAll(new Specification<User>() {
			/**
			 * <p>
			 * Title: toPredicate
			 * </p>
			 * <p>
			 * Description:带条件的分页查询
			 * </p>
			 * 
			 * @param root
			 * @param query
			 * @param cb
			 * @return
			 * @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.persistence.criteria.Root,
			 *      javax.persistence.criteria.CriteriaQuery,
			 *      javax.persistence.criteria.CriteriaBuilder)
			 */
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// TODO Auto-generated method stub
				List<Predicate> predicateOrList = new ArrayList<Predicate>();
				List<Predicate> predicateList = new ArrayList<Predicate>();
				int statu = 0;

				String str = protocol.getInputStr();

				String status = protocol.getStatus();

				if (!StringUtils.isEmpty(str)) {
					predicateOrList.add(cb.like(root.get("name").as(String.class), "%" + str + "%"));
					predicateOrList.add(cb.like(root.get("loginName").as(String.class), "%" + str + "%"));
					predicateOrList.add(cb.like(root.get("telNumber").as(String.class), "%" + str + "%"));
				}

				if (!StringUtils.isEmpty(status)) {
					if (status.equals("1")) {
						statu = 1;
						predicateList.add(cb.equal(root.get("status").as(Boolean.class), statu));
					} else {
						statu = 0;
						predicateList.add(cb.equal(root.get("status").as(Boolean.class), statu));
					}
				}

				query.orderBy(cb.desc(root.get("id").as(String.class)));

				Predicate[] predicateOrs = new Predicate[predicateOrList.size()];
				predicateOrs = predicateOrList.toArray(predicateOrs);
				Predicate predicateOr = cb.or(predicateOrs);

				Predicate[] predicates = new Predicate[predicateList.size() + 1];
				predicateList.add(predicateOr);
				predicates = predicateList.toArray(predicates);
				query.where(cb.and(predicates));
				return cb.and(predicates);
			}
		}, this.buildPageRequest(p.getPageNumber(), p.getPageSize()));

		if (!companyPage.getContent().isEmpty()) {
			response.setDate(new XdaoDate());
			response.setData(companyPage);
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("数据返回成功!");
		} else {
			response.setDate(new XdaoDate());
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("数据返回失败!");
		}
		return response;
	}

	/**
	 * @author liuxincheng
	 * @Title: buildPageRequest
	 * @Description: TODO(构建分页请求)
	 * @param @param
	 *            pageNumber
	 * @param @param
	 *            pagzSize
	 * @param @return
	 *            设定文件
	 * @return PageRequest 返回类型
	 * @throws null
	 */
	private PageRequest buildPageRequest(int pageNumber, int pagzSize) {
		return new PageRequest(pageNumber - 1, pagzSize, null);
	}

	/**
	 * <p>
	 * Title: saveAccount
	 * </p>
	 * <p>
	 * Description: 添加管理员
	 * </p>
	 * 
	 * @param protocol
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#saveAccount(com.fire.control.system.support.protocol.account.AccountRequestProtocol)
	 */
	@Override
	public ResponseProtocol saveAccount(AccountRequestProtocol protocol, UserDTO user) {
		protocol.setTaskuuid(UUID.randomUUID().toString());
		ResponseProtocol response = protocolSelector.choose(protocol);

		User parentUser = userRepository.findOne(user.getUserId());
		User u = protocol.getUser();

		// 判断输入账号是否唯一
		List<User> validateUser = userMapper.getUserByLoginName(u.getLoginName());

		if (validateUser != null && validateUser.size() > 0) {
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("该用户已经存在");
			return response;
		}

		Company c = parentUser.getCompany();

		u.setCreateTime(new XdaoDate());
		u.setCompany(c);

		String passWord = XdaoPassword.getPassword();
		u.setPassword(XdaoPassword.encrypt(passWord));

		// 发送密码给用户
		smsUtil.sendSmsPwd(u.getTelNumber(), u.getLoginName(), passWord);

		User returnUser = accountRepositoty.saveAndFlush(u);

		if (returnUser != null) {
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("管理员添加成功!");
			response.setDate(new XdaoDate());
			response.setData(returnUser);
		} else {
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("管理员添加失败!");
			response.setDate(new XdaoDate());
		}
		return response;
	}

	/**
	 * <p>
	 * Title: saveRole
	 * </p>
	 * <p>
	 * Description: 用户分配角色
	 * </p>
	 * 
	 * @param protocol
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#userAssignRoles(com.fire.control.system.support.protocol.account.AccountRequestProtocol)
	 */
	@Override
	public ResponseProtocol userAssignRoles(AccountRequestProtocol protocol, UserDTO user) {
		// TODO Auto-generated method stub
		ResponseProtocol response = protocolSelector.choose(protocol);

		User u = userRepository.findOne(protocol.getuId());

		Collection<Role> roles = new ArrayList<Role>();

		for (String id : protocol.getRoleIds()) {
			Role r = roleRepository.findOne(id);
			roles.add(r);
		}
		u.setRole(roles);

		User returnUser = accountRepositoty.saveAndFlush(u);
		if (!returnUser.equals(null)) {
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("角色分配成功!");
			response.setDate(new XdaoDate());
			response.setData(returnUser);
		} else {
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("角色分配失败!");
			response.setDate(new XdaoDate());
		}
		return response;
	}

	/**
	 * <p>
	 * Title: getLogList
	 * </p>
	 * <p>
	 * Description: 获得操作日志列表
	 * </p>
	 * 
	 * @param protocol
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#getLogList(com.fire.control.system.support.protocol.account.AccountRequestProtocol)
	 */
	@Override
	public ResponseProtocol getLogList(AccountRequestProtocol protocol, Pageable p) {
		// TODO Auto-generated method stub
		ResponseProtocol response = protocolSelector.choose(protocol);

		List<SysLogResultDTO> sysLogResult = new ArrayList<SysLogResultDTO>();

		Page<SystemLog> systemLogs = systemLogRepository
				.findAll(this.buildPageRequest(p.getPageNumber(), p.getPageSize()));

		User u = null;

		SysLogResultDTO sysLogResultDTO = null;
		Resource resources = null;
		for (SystemLog sl : systemLogs) {
			resources = new Resource();
			sysLogResultDTO = new SysLogResultDTO();
			u = userRepository.findOne(sl.getMonitorTargetId());

			sysLogResultDTO.setUserName(u.getName());
			sysLogResultDTO.setSystemLog(sl);

			resources = sl.getResource();
			sysLogResultDTO.setResource(resources);

			sysLogResult.add(sysLogResultDTO);
		}

		Map<String, Object> returnMap = resultPageUtil.resultPage(new PageInfo<SysLogResultDTO>(sysLogResult),
				sysLogResult);

		if (!returnMap.equals(null)) {
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("数据返回成功!");
			;
			response.setDate(new XdaoDate());
			response.setData(returnMap);
		} else {
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("数据返回失败!");
			response.setDate(new XdaoDate());
		}
		return response;
	}

	/**
	 * <p>
	 * Title: gerLogsByCondition
	 * </p>
	 * <p>
	 * Description: 通过条件获得操作日志列表
	 * </p>
	 * 
	 * @param protocol
	 * @param p
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#gerLogsByCondition(com.fire.control.system.support.protocol.account.AccountRequestProtocol,
	 *      org.springframework.data.domain.Pageable)
	 */
	@Override
	public ResponseProtocol gerLogsByCondition(AccountRequestProtocol protocol, Pageable p) {
		// TODO Auto-generated method stub
		ResponseProtocol response = protocolSelector.choose(protocol);

		Page<SystemLog> systemLogPage = systemLogRepository.findAll(new Specification<SystemLog>() {
			/**
			 * <p>
			 * Title: toPredicate
			 * </p>
			 * <p>
			 * Description:带条件的分页查询
			 * </p>
			 * 
			 * @param root
			 * @param query
			 * @param cb
			 * @return
			 * @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.persistence.criteria.Root,
			 *      javax.persistence.criteria.CriteriaQuery,
			 *      javax.persistence.criteria.CriteriaBuilder)
			 */
			@Override
			public Predicate toPredicate(Root<SystemLog> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				// TODO Auto-generated method stub
				List<Predicate> predicateList = new ArrayList<Predicate>();
				// int statu = 0;
				String accountName = protocol.getUser().getName();
				String monitorContext = protocol.getSystemLog().getMonitorContext();
				// String menus = protocol.getSystemLog().getMonitorTargetId();
				Date createTime = protocol.getSystemLog().getCreateTime();
				// boolean status = protocol.getU().getStatus();

				if (!StringUtils.isEmpty(accountName)) {
					predicateList
							.add(cb.like(root.get("monitorTargetLoginName").as(String.class), "%" + accountName + "%"));
				}

				if (!StringUtils.isEmpty(monitorContext)) {
					predicateList.add(cb.like(root.get("monitorContext").as(String.class), "%" + monitorContext + "%"));
				}

				if (!StringUtils.isEmpty(createTime)) {
					predicateList.add(cb.like(root.get("createTime").as(String.class), "%" + createTime + "%"));
				}

				Predicate[] predicates = new Predicate[predicateList.size()];
				predicates = predicateList.toArray(predicates);
				query.where(cb.and(predicates));
				return cb.and(predicates);
			}
		}, this.buildPageRequest(p.getPageNumber(), p.getPageSize()));

		if (!systemLogPage.getContent().isEmpty()) {
			ResponseMessage.CODE_200.messageToProtocol(response);
			response.setDate(new XdaoDate());
			response.setData(systemLogPage);
		} else {
			Message_Response.FAIL.messageToProtocol(response);
			response.setDate(new XdaoDate());
			response.setData(systemLogPage);
		}
		return response;
	}

	/**
	 * <p>
	 * Title: getResourcesByUser
	 * </p>
	 * <p>
	 * Description: 获取用户下资源菜单
	 * </p>
	 * 
	 * @param requestProtocol
	 * @param user
	 * @return
	 * @see com.fire.control.system.module.login.service.ILoginService#getResourcesByUser(com.fire.control.system.support.protocol.login.LoginRequestProtocol,
	 *      com.fire.control.system.dto.UserDTO)
	 */
	@Override
	public ResponseProtocol getResourcesByUser(LoginRequestProtocol requestProtocol, UserDTO user) {
		// TODO Auto-generated method stub
		ResponseProtocol response = protocolSelector.choose(requestProtocol);

		User u = userRepository.findOne(user.getUserId());

		List<Resource> resourceList = new ArrayList<Resource>();
		Collection<Role> roleList = u.getRole();

		for (Role r : roleList) {
			resourceList.addAll(r.getResources());
		}
		if (!resourceList.isEmpty() && resourceList.size() > 0) {
			response.setData(resourceList);
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("数据获取成功!");
		} else {
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("数据获取失败!");
		}
		return response;
	}

	/**
	 * <p>
	 * Title: updateAccount
	 * </p>
	 * <p>
	 * Description: 修改管理员
	 * </p>
	 * 
	 * @param protocol
	 * @param user
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#updateAccount(com.fire.control.system.support.protocol.account.AccountRequestProtocol,
	 *      com.fire.control.system.dto.UserDTO)
	 */
	@Override
	public ResponseProtocol updateAccount(AccountRequestProtocol protocol, UserDTO user) {
		// TODO Auto-generated method stub
		ResponseProtocol response = protocolSelector.choose(protocol);

		User u = userRepository.findOne(protocol.getuId());
		User parmUser = protocol.getUser();

		u.setUser(parmUser);

		User returnUser = userRepository.saveAndFlush(u);

		if (returnUser != null) {
			response.setData(returnUser);
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("账户信息修改成功!");
		} else {
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("账户信息修改失败!");
		}
		return response;
	}

	/**
	 * <p>
	 * Title: deleteAccount
	 * </p>
	 * <p>
	 * Description: 删除管理员
	 * </p>
	 * 
	 * @param protocol
	 * @param user
	 * @return
	 * @see com.fire.control.system.module.system.service.IAccountManagerService#deleteAccount(com.fire.control.system.support.protocol.account.AccountRequestProtocol,
	 *      com.fire.control.system.dto.UserDTO)
	 */
	@Override
	public ResponseProtocol deleteAccount(AccountRequestProtocol protocol, UserDTO user) {
		// TODO Auto-generated method stub
		ResponseProtocol response = protocolSelector.choose(protocol);

		User u = userRepository.findOne(protocol.getuId());
		
		u.setStatus(false);
		
		User returnUser = userRepository.saveAndFlush(u);
		
		if (returnUser != null) {
			response.setData(returnUser);
			ResponseMessage.CODE_200.messageToProtocol(response).setMessage("账户信息删除成功!");
		} else {
			ResponseMessage.CODE_400.messageToProtocol(response).setMessage("账户信息删除失败!");
		}
		return response;
	}
}
